home *** CD-ROM | disk | FTP | other *** search
- /* Here we have SPLIT.C written for the Turbo C compiler. While it was written
- * using Tubro C version 1.5 it will compile under version 1.0 and with only a
- * slight modification also under Microsoft C ver 5.0 and QuickC ver 1.0. To
- * have the program compile under MSC 5.0 all you need do is insert another
- * include directive: #include <sys\types.h> and delete the line
- *
- * case EINVACC: printf("Invalid access code"); break;
- *
- * in the filerr() function. With Quick C you also have to make sure that the
- * fdopen() function is included in the library that you link with split.obj.
- * For information on how to do this see section 10.1.3 "Standard Library
- * Routines in Quick Libraries" on page 239 of the Quick C Programmer's Guide.
- *
- * The code was written with tab stops of size 3 and a maximum of 80 columns.
- * And it is hereby given to the Public Domain by Charles Lazo III, CIS User ID
- * 72210,17 (enjoy!) */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <io.h>
- #include <sys\stat.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <string.h>
-
- #define MAXFNAMES 31 /* maximum number of output files */
- #define Y 89 /* for a yes response */
- #define y 121 /* ditto */
- #define BUFSIZE 2048 /* buffer size for transfer from input to output files */
-
- void saywhat(int problem); /* tell user proper syntax */
- int parse_ratios(char *ratio); /* parse ratio argument */
- void checkfile(char *fname); /* check if file exists */
- int gethandle(char *fname); /* obtains file handles for output files */
- void filerr(int handle, char *fname); /* file open error handler */
- void splitfile(FILE *s); /* write a split output file */
- void allocerr(void *ptr); /* memory allocation error handler */
-
- int accs; /* to obtain file access mode */
- int numoutfiles; /* store the number of output files */
- long flen[MAXFNAMES]; /* file lengths for output files */
- long filebytes; /* set to bytes written to each output file */
- long foff; /* tracks offset of pointer in input file */
- void *buffer; /* set to I/O buffer of input/output files */
- FILE *in_stream; /* pointer to input file stream */
-
- main(int argc, char **argv) {
-
- int i; /* multipurpose loop counter */
- int in_handle, out_handle; /* store handles for input and output files */
- long rationum; /* store for relations to ratio numbers */
- long inflen; /* store for input file length */
- FILE *stream[MAXFNAMES]; /* array of pointers to output file streams */
-
- if (argc == 1) /* no command line parameters? */
- saywhat(0); /* that's right, give syntax and exit */
-
- accs = O_RDONLY | O_BINARY; /* access mode of input file */
- in_handle = open(argv[1], accs); /* open the input file */
- filerr(in_handle, argv[1]); /* check for file open error */
- in_stream = fdopen(in_handle, "r"); /* set stream of input file */
-
- numoutfiles = argc - 3; /* retain number of output files */
- if (!parse_ratios(argv[argc - 1])) /* parse the ratios argument */
- saywhat(1); /* and send syntax if error */
-
- rationum = 0; /* initialize sum */
- for (i = 0; i < numoutfiles; i++)
- rationum += flen[i]; /* sum ratio numbers */
-
- inflen = filelength(in_handle); /* retain size of input file */
-
- if (rationum > inflen || rationum == 0) /* sum of ratio numbers must be */
- saywhat(1); /* no larger than infile length & != 0 */
-
- rationum = inflen / rationum; /* compute base to scale up */
-
- for (i = 0; i < numoutfiles - 1; i++) {
- flen[i] *= rationum; /* scale 'em up */
- }
-
- rationum = 0; /* last file length gets excess */
- for (i = 0; i < numoutfiles - 1; i++)
- rationum += flen[i];
- flen[numoutfiles - 1] = inflen - rationum;
-
- for (i = 1; i <= numoutfiles; i++)
- checkfile(argv[i + 1]); /* check if output files exists */
-
- for (i = 0; i < numoutfiles; i++) {
- out_handle = gethandle(argv[i + 2]); /* open output files and */
- stream[i] = fdopen(out_handle, "w"); /* associate with streams */
- }
-
- foff = -1L * BUFSIZE; /* so offset == 0 on splitfile() entry */
- for (i = 0; i < numoutfiles; i++) { /* write numoutfiles of output files */
- filebytes = flen[i]; /* get an established outfile length */
- splitfile(stream[i]); /* write an outfile */
- printf("\nFinished file %s", argv[i + 2]);
- }
- }
-
- void saywhat(int problem) {
- if (problem)
- printf("\nSay what???\n");
- printf("\nSyntax is SPLIT INFILE file1 file2...fileN n1:n2...:nN");
- printf("\n\n");
- printf("Where the file INFILE remains unaltered, but its contents will\n");
- printf("be copied into the N files: file1, file2,..., fileN, so the DOS\n");
- printf("command \"copy/b file1+file2+...+fileN total\" will yield a file\n");
- printf("\"total\" identical to INFILE. The last argument, n1:n2...:nN,\n");
- printf("consists of N numbers separated by colons (no spaces allowed)\n");
- printf("that represent size ratios of the N output files, i.e.,\n\n");
- printf(" length(fileI) = nI * [length(INFILE) / (n1 + n2 +...+ nN)]\n");
- printf(" (for all I such that 1 <= I < N).\n\n");
- printf("The last output file gets any excess bytes.\n");
- exit(1);
- }
-
- int parse_ratios(char *ratio) { /* returns zero if error, else nonzero */
- int i;
- char *ratioptr; /* set to individual ratio numbers prior to atol() */
- char *colonptr; /* set to colons in ratio argument */
- char colon = ':'; /* colon to find in ratio argument */
- colonptr = ratio; /* initialize to first ratio number */
- ratioptr = ratio; /* and set ratioptr for first atol() */
- for (i = 0; i < numoutfiles; i++) {
- if (i == numoutfiles - 1) { /* no colon at end; so, special case */
- flen[i] = atol(ratioptr); /* set last file length ratio */
- return(1); /* and return success indication */
- }
- colonptr = strchr(ratioptr, colon); /* point to next colon */
- if (colonptr == NULL) /* failure if no colon in argument */
- return(0);
- colonptr[0] = 0; /* place a null at colon position */
- flen[i] = atol(ratioptr); /* convert a file length ratio number */
- colonptr++; /* point to next number */
- ratioptr = colonptr; /* and set ratioptr for next atol() */
- }
- }
-
- void checkfile(char *fname) { /* if outfile exists prompt user */
- int ch;
- if (access(fname, 0) != -1) {
- printf("\nFile %s exists. Overwrite (y/n)? ", fname);
- ch = getche();
- if (!(ch == y || ch == Y)) {
- printf("\n");
- exit(1); /* not a 'yes' response, so abort */
- }
- printf("\n");
- }
- }
-
- int gethandle(char *fname) {
- int permission, handle;
- accs = O_RDWR | O_CREAT | O_TRUNC | O_BINARY; /* create file overwriting */
- /* any existing file */
- permission = S_IWRITE; /* set attribute to read/write */
- handle = open(fname, accs, permission); /* open an output file */
- filerr(handle, fname); /* check for file open error */
- return(handle); /* no error, then return handle */
- }
-
- void filerr(int handle, char *fname) {
- if (handle == -1) { /* a handle of -1 signals an error */
- printf("\nFile open error: ");
- switch (errno) { /* external 'errno' gives type of error */
- case ENOENT: printf("Path or file name not found"); break;
- case EMFILE: printf("Too many open files"); break;
- case EACCES: printf("Permission denied"); break;
- case EINVACC: printf("Invalid access code"); break;
- }
- printf(" for file -> %s\n", fname);
- exit(1);
- }
- }
-
- void splitfile(FILE *stream) { /* this function puts infile to outfiles */
- buffer = malloc(BUFSIZE); /* begin with preassigned buffer size */
- allocerr(buffer); /* insure successful allocation */
- while (filebytes) { /* loop till all bytes transferred */
- foff += BUFSIZE; /* bump input file pointer */
- if (filebytes >= BUFSIZE) { /* bytes left >= buffer size? */
- fseek(in_stream, foff, SEEK_SET); /* yeah, move infile pointer */
- fread(buffer, BUFSIZE, 1, in_stream); /* get bytes to buffer */
- fwrite(buffer, BUFSIZE, 1, stream); /* then write them to outfile */
- filebytes -= BUFSIZE; /* reduce byte count */
- }
- else { /* deal with remainder */
- free(buffer); /* release large buffer */
- buffer = malloc(filebytes); /* and make smaller one */
- allocerr(buffer); /* check for error */
- fseek(in_stream, foff, SEEK_SET); /* set infile pointer */
- fread(buffer, filebytes, 1, in_stream);/* infile bytes to buffer */
- fwrite(buffer, filebytes, 1, stream); /* write bytes to outfile */
- foff = foff + filebytes - BUFSIZE; /* set for next outfile */
- free(buffer); /* free memory for next time */
- filebytes = 0; /* for exit of while */
- }
- }
- }
-
- void allocerr(void *ptr) { /* send message and abort if memory error */
- if (ptr == NULL) {
- printf("\nCan't allocate needed memory.\n");
- exit(1);
- }
- }